1. 상속 관계
상속이란
기존의 클래스를 사용하여 새로운 클래스를 작성하는 것이다. 상속을 통해서 클래스를 작성하면 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고 코드를 공톡적으로 관리할 수 있다. 상속을 받게 되면 조상 클래스의 멤버 변수 및 메서드를 사용할 수 있다.
- 문법
class 자손 클래스 extends 부모 클래스 { }
- 조상과 자손
- 상속해 주는 클래스를 조상 클래스 라고 한다
- 상속 받는 클래스를 자손 클래스라고 한다.
class Child extends Parent{ //자손 //조상 }
- 알고 가자
- 생성자와 초기화 블럭은 상속되지 않는다. 멤버(변수, 메서드)만 상속된다.
- 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.
- 자손 클래스의 인스턴스를 생성하면 조상 클래스의 멤버도 함께 생성된다.
- C++와 같은 언어에선 다중 상속을 지원하지만 java에서는 다중 상속을 지원하지 않는다.
다중 상속?
- 여러가지 부모 클래스를 상속받는 것을 의미한다.
Object 클래스
Object 클래스는 모든 클래스 상속 계층도의 최상위에 있는 조상 클래스이다. 아무것도 상속 받지 않는 클래스는 자동으로 Object 클래스를 상속받는다.
- toString() equals() 와 같은 함수도 Object클래스에 정의되어 있기 때문에 사용할 수 있었다.
super
➡️ super?
super은 자손 클래스에서 조상 클래스로부터 상속 받은 멤버를 참조하는데 사용하는 참조 변수이다.
➡️ 언제 사용하는가
조상 클래스로부터 상속받은 멤버도 자손 클래스 자신의 멤버임으로 super대신 this를 사용할 수 있다. 그래도 조상 클래스의 멤버와 자손 클래스의 멤버가 중복 정의되어 서로 구별해야 하는 경우에만 super을 사용하는 것이 좋다.
➡️ 예제
- super 사용하기
class Test{ int a; int b; Test(){ a = 3; b = 4; } Test(int a, int b){ this.a = a; this.b = b; } } class Stest extends Test{ Stest(){ super(); } Stest(int a, int b){ super(a, b); } } public class TestCode extends Test{ public static void main(String[] args) { Stest st = new Stest(5,6); System.out.printf("a= %d, b = %d",st.a, st.b); } }
- super.멤버로 값 가져오기
class Parent2{ int x = 10; } class Child2 extends Parent2{ int x = 20; void method() { System.out.println(this.x); //20 System.out.println(super.x); //10 } } class c7_2_4 { public static void main(String[] args) { Child2 c = new Child2(); c.method(); } }
결과
- 똑같은 변수 x 지만 한개는 부모로부터 상속받았기 떄문에 20 한개는 10이 나온다.
➡️ super() - 조상 클래스의 생성자
- 조상 클래스의 생성자를 호출하는데 사용된다. 생성자의 첫 줄에서 조상 클래스의 생성자를 호출해야하며 만약 super() 구문을 생성자의 첫 줄에서 생성해주지 않는다면 컴파일러가 자동적으로 super()을 수행한다.
- 조상 클래스의 생성자에 매개변수가 있을 경우 super(매개변수) 를 넣어줘야 한다.
2. 포함 관계
포함 관계란
클래스 간에 포함 관계를 맺어준다. 한 클래스의 맴버변수로 다른 클래스의 참조 변수를 선언하는 것을 말한다.
- 문법
class test2{ test1 t = new test1(); //포함될 클래스의 참조변수를 선언해주면 된다. }
상속? 포함? 뭘 써야할까
~은 ~이다 → 상속
~은 ~를 가지고 있다. → 포함
- example
class Circle 은 Point이다 x class Circle 은 Point를 가지고 있다 o -> 포함 관계가 더 잘어울림 class Circle 은 도형이다. o class Circle 은 도형을 가지고 있다. x -> 상속 관계가 더 잘 어울림
- 포함 관계 예시 코드 (카드 뽑기)
class Deck{ final int CARD_NUM = 52; Card cardArr[] = new Card[CARD_NUM]; Deck(){ int i = 0; //카드 각 13장씩 4개의 종류를 생성 총 52장 i=52 for(int k=Card.KIND_MAX; k > 0; k--){ for(int n=0; n < Card.NUM_MAX; n++){ cardArr[i++] = new Card(k, n+1); } } } Card pick(int index){ return cardArr[index]; } Card pick(){ int index = (int)(Math.random() * CARD_NUM); return pick(index); } void shuffle(){ for(int i = 0; i < cardArr.length; i++){ int r = (int)(Math.random() * CARD_NUM); Card temp = cardArr[i]; cardArr[i] = cardArr[r]; cardArr[r] = temp; } } } class Card{ static final int KIND_MAX = 4; //문양 종류 static final int NUM_MAX = 13; //무늬 별 카드 수 static final int SPADE = 4; static final int DIAMOND = 3; static final int HEART = 2; static final int CLOVER = 1; int kind; int number; Card(){ this(SPADE, 1); } Card(int kind, int number){ this.kind = kind; this.number = number; } public String toString(){ String[] kinds = {"", "CLOVER", "HEART", "DIAMOND", "SPADE"}; String numbers = "0123456789TJQK"; return "kind : " + kinds[this.kind] + ", number : " + numbers.charAt(this.number); } } class c7_2_3 { public static void main(String[] args) { Deck d = new Deck(); Card c = d.pick(0); System.out.println(c); //System.out.println(c.toString()) 와 같다 d.shuffle(); c = d.pick(0); System.out.println(c); } }
- 해당 코드에서는 DECK이라는 Class가 Card라는 Class를 포함한다.
- Deck class는 Card클래스의 참조 객체 배열을 만들어서 사용한다.
- 4가지 문양마다 13개의 카드가 존재하며 해당 카드를 생성한 후 섞고 가장 맨위에 있는 카드를 내놓는다.
3. 오버라이딩
오버라이딩 이란
➡️ 의미
오버라이딩은 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것을 오버라이딩이라고 한다.
➡️ 조건
1) 이름이 같아야 한다
2) 매개변수가 같아야 한다.
3) 반환 타입이 같아야 한다.
→ 즉 선언하는 부분이 같아야 한다.
➡️ 주의사항
1) 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
2) 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.
3) 인스턴스메서드를 static메서드로 또는 그 반대로 변경할 수 없다.
오버라이딩 vs 오버로딩
- 오버로딩 : 기존에 없는 새로운 메서드를 정의하는 것
- 오버라이딩 : 상속받은 메서드의 내용을 변경하는 것